import os
from http import HTTPStatus
from dashscope import Application
from fastapi import APIRouter, Body, Request, Depends
from configs.other_config import DASHSCOPE_API_KEY, ALGORITHM, CHAT_WITH_LERONGROU_APPID, CHAT_WITH_XIYANGYANG_APPID
from configs.kb_config import GO_SERVICE_SECRET_KEY, ENVIRONMENT
from configs.logging_config import configure_logging
from server.db.models.message_model import MarsXChatWithLerongrongSession, MarsXChatWithXiyangyangSession
from server.db.models.memory_model import Memory
from typing import Optional, Union, Generator
from dashscope.app.application import ApplicationResponse
from server.utils import create_chat_response, BaseResponse, decode_verify_token
from server.bailian.memory_client import client as memory_client
from loguru import logger
from sse_starlette.sse import EventSourceResponse
from server.db.session import get_db
from sqlalchemy.orm import Session
from sqlalchemy import and_
from datetime import datetime, timedelta
import pytz
import asyncio
from configs.other_config import STREAM_RETURN_INTERVAL

configure_logging()
router = APIRouter()

@router.post("/bailian/v1/chat/chat_with_xiyangyang_lerongrong")
async def chat_with_xiyangyang_lerongrong_v1(uid: str = Body(..., embed=True, description="用户ID"), 
                            conversation_id: Optional[str] = Body(None, embed=True, description="会话ID"),
                            stream: bool = Body(True, embed=True, description="是否流式输出"),
                            nickname: str = Body(..., embed=True, description="昵称"),
                            character: str = Body(..., embed=True, description="性格"),
                            query: str = Body(..., embed=True, description="用户输入"),
                            request: Request = None,
                            db: Session = Depends(get_db)):
    
    # 解码token
    try:
        token = decode_verify_token(request, GO_SERVICE_SECRET_KEY, ALGORITHM)
    except Exception as e:
        return BaseResponse(code=401, msg="Token is invalid", data={"error": str(e.detail.get('msg'))})
    
    memory_object = db.query(Memory).filter(Memory.user_id == uid, Memory.memory_id != "").first()
    if memory_object is not None:
        memory_id = memory_object.memory_id
    else:
        memory = memory_client.create_memory(description=f"MarsXAPP_{ENVIRONMENT}_{uid}")
        memory_id = memory["memoryId"]
        request_id = memory["requestId"]
        memory_object = Memory(
            user_id=uid,
            memory_id=memory_id,
            workspace_id=memory_client.config.workspace_id,
            request_type=0,
            request_id=request_id
        )
        try:
            db.add(memory_object)
            db.commit()
        except Exception as e:
            db.rollback()
            logger.error(f"创建记忆体时数据库操作失败 用户ID: {uid} | 错误信息: {e}")
            return BaseResponse(
                code=HTTPStatus.INTERNAL_SERVER_ERROR,
                msg="创建记忆体时数据库操作失败",
                data={
                    "error_type": "500",
                    "error_message": str(e),
                    "uid": uid,
                    "memory_id": memory_id,
                    "workspace_id": memory_client.config.workspace_id,
                    "request_type": 0,
                    "request_id": request_id
                }
            )
    

    """
    与喜洋洋或乐融融对话
    """
    if nickname == "喜洋洋":
        app_id = CHAT_WITH_XIYANGYANG_APPID
        session_model = MarsXChatWithXiyangyangSession
    elif nickname == "乐融融":
        app_id = CHAT_WITH_LERONGROU_APPID
        session_model = MarsXChatWithLerongrongSession
    else:
        return BaseResponse(code=400, msg="昵称无效")
    
    beijing_timezone = pytz.timezone("Asia/Shanghai")
    beijing_time = datetime.now(beijing_timezone)
    beijing_time_str = beijing_time.strftime("%Y-%m-%d %H:%M:%S")
    # 星期几
    weekday = beijing_time.weekday()
    weekday_str = ["一", "二", "三", "四", "五", "六", "日"][weekday]
    biz_params = {
        "user_prompt_params": {
            "nickname": nickname,
            "character": character,
            "time": beijing_time_str + " 星期" + weekday_str
        }
    }

    # # 获取该用户的会话ID
    # session_object = db.query(session_model).filter(
    #     and_(session_model.user_id == uid, session_model.conversation_id != "")
    #     ).first()
    # if session_object is not None:
    #     # 获取用户的会话ID
    #     conversation_id = session_object.conversation_id
    
    # responses = Application.call(
    #             # 若没有配置环境变量，可用百炼API Key将下行替换为：api_key="sk-xxx"。但不建议在生产环境中直接将API Key硬编码到代码中，以减少API Key泄露风险。
    #             api_key=os.getenv("DASHSCOPE_API_KEY", DASHSCOPE_API_KEY), 
    #             app_id=app_id,
    #             prompt=query,
    #             stream=True,  # 流式输出
    #             incremental_output=True,
    #             biz_params=biz_params,
    #             session_id=conversation_id,
    #             memory_id=memory_id)  # 增量输出

    # session_object = db.query(session_model).filter(
    #     and_(session_model.user_id == uid, 
    #          session_model.conversation_id != "")
    #     ).order_by(session_model.created_time.desc()).first()
    
    # # 判断最新会话是否超时（阿里云说session_id有效期为一小时，但是这里自定义为10分钟）
    # valid_session = False
    # if session_object:
    #     if datetime.now() - session_object.created_time < timedelta(minutes=10):
    #         valid_session = True
    #         conversation_id = session_object.conversation_id
    #     else:
    #         # 删除过期会话
    #         db.delete(session_object)
    #         db.commit()
    #         conversation_id = None
    # else:
    #     conversation_id = None

    # 获取该用户的最新会话（按创建时间倒序）
    session_object = db.query(session_model).filter(
        and_(session_model.user_id == uid, 
             session_model.conversation_id != "")
        ).order_by(session_model.created_time.desc()).first()

    # 获取会话的首次创建时间（需要查询同会话ID的最早记录）
    first_created_time = None
    if session_object:
        first_session = db.query(session_model).filter(
            session_model.conversation_id == session_object.conversation_id
        ).order_by(session_model.created_time.asc()).first()
        first_created_time = first_session.created_time if first_session else None 
    # 双重时间校验
    valid_session = False
    if session_object and first_created_time:
        last_active_expired = datetime.now() - session_object.created_time > timedelta(minutes=10)
        first_create_expired = datetime.now() - first_created_time > timedelta(minutes=50)
        
        if not last_active_expired and not first_create_expired:
            valid_session = True
            conversation_id = session_object.conversation_id
        else:
            # 仅重置会话ID（保留历史记录）
            # 生成新会话ID（由阿里云API返回）
            conversation_id = None  
            
            # 可选：标记旧会话为已过期
            db.query(session_model).filter(
                session_model.conversation_id == session_object.conversation_id
            ).update({"is_expired": True})
            db.commit()
    else:
        conversation_id = None

    # 只有当有有效会话时才传递session_id
    call_params = {
        "api_key": os.getenv("DASHSCOPE_API_KEY", DASHSCOPE_API_KEY),
        "app_id": app_id,
        "prompt": query,
        "stream": True,
        "incremental_output": True,
        "biz_params": biz_params,
        "memory_id": memory_id
    }
    if valid_session:
        call_params["session_id"] = conversation_id

    responses = Application.call(**call_params)
    async def event_generator(responses: Union[ApplicationResponse, Generator[ApplicationResponse, None, None]]):
        full_answer = ""
        session_id = None
        request_id = None
        code = None
        for response in responses:
            # response.output.session_id # 会话ID
            if response.status_code != HTTPStatus.OK:
                request_id = response.request_id
                code = response.status_code
                session_id = ""
                session_object = session_model(
                    user_id=uid,
                    conversation_id=session_id,
                    request_id=request_id,
                    user_input=query
                )
                try:
                    db.add(session_object)
                    db.commit()
                except Exception as e:
                    db.rollback()
                    logger.error(f"创建会话时数据库操作失败 用户ID: {uid} | 用户输入: {query} | 错误信息: {e}")
                logger.error(f"错误信息: {response.code} | {response.message} 请求ID: {request_id} 用户ID: {uid} 会话ID: {session_id} 用户输入: {query}")
                await asyncio.sleep(STREAM_RETURN_INTERVAL)
                yield create_chat_response(
                    response_text=None,
                    instruction="-1",
                    request_id=request_id,
                    finish=True,
                    code=code,
                    data_content={
                        "error_type": response.code,
                        "error_message": response.message
                    }
                )
                return
            else:
                if stream:
                    answer = response.output.text
                    full_answer += answer
                    request_id = response.request_id
                    code = response.status_code

                    # 新增：返回时间
                    beijing_timezone = pytz.timezone("Asia/Shanghai")
                    current_time = datetime.now(beijing_timezone).strftime("%Y-%m-%d %H:%M:%S")

                    await asyncio.sleep(STREAM_RETURN_INTERVAL)
                    yield create_chat_response(
                        response_text=answer,
                        instruction="-1",
                        request_id=request_id,
                        finish=False,
                        code=code,
                        data_content={
                            "time": current_time
                        }
                    )
            session_id = response.output.session_id
        session_object = session_model(
            user_id=uid,
            conversation_id=session_id,
            request_id=request_id,
            user_input=query,
            assistant_answer=full_answer
        )
        try:
            db.add(session_object)
            db.commit()
        except Exception as e:
            db.rollback()
            logger.error(f"创建会话时数据库操作失败 用户ID: {uid} | 用户输入: {query} | 错误信息: {e}")
        logger.info(f"用户{uid}的会话ID为{session_id} | 用户输入为：{query} | 智能体回答为：{full_answer}")
        await asyncio.sleep(STREAM_RETURN_INTERVAL)
        yield create_chat_response(
            response_text=full_answer,
            instruction="-1",
            request_id=request_id,
            finish=True,
            code=code,
            data_content={
                "time": current_time
            }
        )
    return EventSourceResponse(event_generator(responses))